﻿using Castle.DynamicProxy;
using Microsoft.AspNetCore.DataProtection.KeyManagement;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Caching.Memory;
using MyCommon;
using MyCommon.Caches;
using MyExtension.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace MyExtension.AOP
{
    public class MyCacheAop : CacheAopBase
    {
        private readonly IMemoryCache _cache;
        private readonly ICaching _caching;

        public MyCacheAop(IMemoryCache cache, ICaching caching)
        {
            _cache = cache;
            _caching = caching;
        }
        public override void Intercept(IInvocation invocation)
        {
            var method = invocation.MethodInvocationTarget ?? invocation.Method;
            var cachingAttribute = method.GetCustomAttributes(true).FirstOrDefault(x => x.GetType() == typeof(CachingAttribute));
            if (cachingAttribute is CachingAttribute cache)
            {
                //使用缓存
                // 1.看看缓存中是否存在
                // 1.1 先定义缓存key
                string cacheKey = GetCustomCacheKey(invocation);

                // 1.2 根据key去缓存中获取数据，拿到了就直接返回，否则继续往后执行
                if (_caching.Exists(cacheKey))
                {
                    Type returnType;
                    if (typeof(Task).IsAssignableFrom(method.ReturnType))
                    {
                        returnType = method.ReturnType.GenericTypeArguments.FirstOrDefault()!;
                    }
                    else
                    {
                        returnType = method.ReturnType;
                    }
                    dynamic cacheValue = _caching.Get(returnType,cacheKey);
                    invocation.ReturnValue =(typeof(Task).IsAssignableFrom(method.ReturnType))?Task.FromResult(  cacheValue):cacheValue;
                    return;
                }

                // 2.执行后续方法拿到结果
                invocation.Proceed();

                // 3.把结果缓存起来
                if (!string.IsNullOrWhiteSpace(cacheKey))
                {
                    var type = invocation.Method.ReturnType;

                    // var response = invocation.ReturnValue;
                    object response;
                    if (typeof(Task).IsAssignableFrom(type))
                    {
                        dynamic res = invocation.ReturnValue;
                        response = res.Result;
                    }
                    else
                    {
                        response = invocation.ReturnValue;
                    }
                    if (response == null) { response = string.Empty; }
                    _caching.Set(cacheKey, response, TimeSpan.FromMinutes(cache.AbsoluteExpiration));
                    // _cache.Set(cacheKey, response,TimeSpan.FromMinutes(cache.AbsoluteExpiration));
                }
            }
            else
            {
                // 没有缓存直接执行后续方法
                invocation.Proceed();
            }
        }


    }
}
